/* Half Byte Loader is GPL
* Crappy Menu(tm) wololo (One day we'll get something better)
* thanks to N00b81 for the graphics library!
* 
*/

#include <pspsdk.h>
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspctrl.h>
#include <pspdisplay.h>
#include <psppower.h>
#include <string.h>
#include <stdio.h>
#include "graphics.h"
#include "vram.h" 
#include <stdlib.h>
#include <math.h>
#include <pspgu.h>
#include <pspgum.h>
#include "callbacks.h" 

#define RGB(r, g, b) ((r)|((g)<<8)|((b)<<16)) 

#define FOLDERNAME_SIZE 30
#define NB_FOLDERS 400
#define MAXMENUSIZE 20

#define MAX_INDEX_TABLE_SIZE 11 // max number of entries in psf table 
#define MAX_NAME_SIZE 59
#define FILE_BUFFER_SIZE 80

// index table offsets
#define OFFSET_KEY_NAME 0
#define DATA_ALIGN 2
#define DATA_TYPE 3
#define SIZE_OF_VALUE 4
#define SIZE_DATA_AND_PADDING 8
#define OFFSET_DATA_VALUE 12

//initially from eMenu--
typedef struct
{
	unsigned long        APIVersion;
	char       Credits[32];
	char       VersionName[32];
	char       *BackgroundFilename;   // set to NULL to let menu choose.
    char        * filename;   // The menu will write the selected filename there
}	tMenuApi;

PSP_MODULE_INFO("Xenu", 0, 0, 1);
PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER);
PSP_MAIN_THREAD_STACK_SIZE_KB(256);

static unsigned int __attribute__((aligned(16))) list[262144];

char folders[NB_FOLDERS][FOLDERNAME_SIZE] ;
char * cacheFile = "menu.cache";

void * ebootPath;
void *frameBuffer = (void *)0x44000000;

int
selectedColour = 0x0000FFFF,
textColour = 0x00FFFFFF,
backgroundColour = 0x00000000,
currentFile,
isSet,
nbFiles,
showInfo,
refreshType;

/**
* C++ version 0.4 char* style "itoa":
* Written by Lukás Chmela
* Released under GPLv3.
*//* Exit callback */


int exit_callback(int arg1, int arg2, void *common) {
          sceKernelExitGame();
          return 0;
}

/* Callback thread */
int CallbackThread(SceSize args, void *argp) {
          int cbid;

          cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
          sceKernelRegisterExitCallback(cbid);

          sceKernelSleepThreadCB();

          return 0;
}

/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void) {
          int thid = 0;

          thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
          if(thid >= 0) {
                    sceKernelStartThread(thid, 0, 0);
          }

          return thid;
} 
struct Vertex
{
	float u, v;
	unsigned int color;
	float x,y,z;
};
struct Vertex __attribute__((aligned(16))) vertices[12*3] =
{
	{0, 0, 0xff7f0000,-1,-1, 1}, // 0
	{1, 0, 0xff7f0000,-1, 1, 1}, // 4
	{1, 1, 0xff7f0000, 1, 1, 1}, // 5

	{0, 0, 0xff7f0000,-1,-1, 1}, // 0
	{1, 1, 0xff7f0000, 1, 1, 1}, // 5
	{0, 1, 0xff7f0000, 1,-1, 1}, // 1

	{0, 0, 0xff7f0000,-1,-1,-1}, // 3
	{1, 0, 0xff7f0000, 1,-1,-1}, // 2
	{1, 1, 0xff7f0000, 1, 1,-1}, // 6

	{0, 0, 0xff7f0000,-1,-1,-1}, // 3
	{1, 1, 0xff7f0000, 1, 1,-1}, // 6
	{0, 1, 0xff7f0000,-1, 1,-1}, // 7

	{0, 0, 0xff007f00, 1,-1,-1}, // 0
	{1, 0, 0xff007f00, 1,-1, 1}, // 3
	{1, 1, 0xff007f00, 1, 1, 1}, // 7

	{0, 0, 0xff007f00, 1,-1,-1}, // 0
	{1, 1, 0xff007f00, 1, 1, 1}, // 7
	{0, 1, 0xff007f00, 1, 1,-1}, // 4

	{0, 0, 0xff007f00,-1,-1,-1}, // 0
	{1, 0, 0xff007f00,-1, 1,-1}, // 3
	{1, 1, 0xff007f00,-1, 1, 1}, // 7

	{0, 0, 0xff007f00,-1,-1,-1}, // 0
	{1, 1, 0xff007f00,-1, 1, 1}, // 7
	{0, 1, 0xff007f00,-1,-1, 1}, // 4

	{0, 0, 0xff00007f,-1, 1,-1}, // 0
	{1, 0, 0xff00007f, 1, 1,-1}, // 1
	{1, 1, 0xff00007f, 1, 1, 1}, // 2

	{0, 0, 0xff00007f,-1, 1,-1}, // 0
	{1, 1, 0xff00007f, 1, 1, 1}, // 2
	{0, 1, 0xff00007f,-1, 1, 1}, // 3

	{0, 0, 0xff00007f,-1,-1,-1}, // 4
	{1, 0, 0xff00007f,-1,-1, 1}, // 7
	{1, 1, 0xff00007f, 1,-1, 1}, // 6

	{0, 0, 0xff00007f,-1,-1,-1}, // 4
	{1, 1, 0xff00007f, 1,-1, 1}, // 6
	{0, 1, 0xff00007f, 1,-1,-1}, // 5
};

#define BUF_WIDTH (512)
#define SCR_WIDTH (480)
#define SCR_HEIGHT (272)

char* itoa(int value, char* result, int base) {
	// check that the base if valid
	if (base < 2 || base > 36) { *result = '\0'; return result; }
	
	char* ptr = result, *ptr1 = result, tmp_char;
	int tmp_value;
	
	do {
		tmp_value = value;
		value /= base;
		*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
	} while ( value );
	
	// Apply negative sign
	if (tmp_value < 0) *ptr++ = '-';
	*ptr-- = '\0';
	while(ptr1 < ptr) {
		tmp_char = *ptr;
		*ptr--= *ptr1;
		*ptr1++ = tmp_char;
	}
	return result;
}

void saveCache()
{
    SceUID id = sceIoOpen(cacheFile, PSP_O_CREAT | PSP_O_WRONLY | PSP_O_TRUNC, 0777);
    if (id < 0) 
        return;
    sceIoWrite(id, &folders, FOLDERNAME_SIZE * NB_FOLDERS * sizeof(char));
    sceIoClose(id);
}

/*Loads an alternate cached version of the folders
* if sceIoDopen failed
*/
void loadCache()
{
	int i;

    printTextScreen(0, 216 , "->Using a cached version of the folder's contents", textColour);
    SceUID id = sceIoOpen(cacheFile, PSP_O_RDONLY, 0777);
	
    if (id < 0) 
		return;
	
    sceIoRead(id, &folders, FOLDERNAME_SIZE * NB_FOLDERS * sizeof(char));
    sceIoClose(id);    
    
    nbFiles = 0;
    for (i = 0; i < NB_FOLDERS; ++i)
	{
        if (folders[i][0] == 0) 
        {
            break;
        }
        nbFiles++;
    }    
}

void readEbootName(const char * filename, const char * backup, char* name) {

	typedef struct {
		char signature[4];
		int version;
		int offset[8];
	}PBPHeader;

	typedef struct {
		char signature[4];
		int version;
		int offset_key_table;
		int offset_values_table;
		int num_entries; 
	}PSFHeader;

	int fid; // file id
	unsigned char index_table[MAX_INDEX_TABLE_SIZE][16];
	PBPHeader pbpHeader;	
	PSFHeader psfHeader;

	fprintf(stderr, "File is [%s]\n",filename);
	if(!(fid = sceIoOpen(filename, PSP_O_RDONLY, 0777)))
	{
		//LOGSTR0("File is NULL");
        return;
	} 

    /* PBP SECTION */
    sceIoRead(fid, &pbpHeader, sizeof(pbpHeader)); // read in pbp header
    if(!(pbpHeader.signature[1] == 'P' && pbpHeader.signature[2] == 'B' && pbpHeader.signature[3] == 'P')) 
    { 
        strcpy(name, backup);
        strcat(name," (Corrupt or invalid PBP)");
        //LOGSTR0("File not a PBP\n");
        sceIoClose(fid);
        return;
    } 

    /* PSF SECTION */
    sceIoLseek(fid, pbpHeader.offset[0] , PSP_SEEK_SET ); // seeks to psf section - first entry in pbp offset table
    sceIoRead(fid,&psfHeader, sizeof(psfHeader));											// reads in psf header

    //LOGSTR1("PSF number of Entries [%d]\n", psfHeader.num_entries);
    if (psfHeader.num_entries > MAX_INDEX_TABLE_SIZE)
    { 
        strcpy(name, backup);
        strcat(name," (Corrupt or invalid PBP)");
        //LOGSTR0("File not a PBP\n");
        sceIoClose(fid);
        return;
    }    
    sceIoRead(fid,&index_table,((sizeof(unsigned char) * 16 ) * psfHeader.num_entries));
    
    // builds offset [offset_key + Offset_data_value + (data_align * 2)]
    int seek_offset = index_table[(psfHeader.num_entries - 1)][OFFSET_KEY_NAME] + index_table[(psfHeader.num_entries - 1)][OFFSET_DATA_VALUE] + 	(index_table[(psfHeader.num_entries - 1)][DATA_ALIGN] * 2);

    // some offset are not even numbers so they read in some off the null padding
    if (seek_offset % 2 > 0)
    {
        seek_offset++;
    }

    //LOGSTR1("PSF using offset [%d]\n", seek_offset);

    sceIoLseek(fid, seek_offset, PSP_SEEK_CUR);
    sceIoRead(fid,name, (sizeof(char) * index_table[(psfHeader.num_entries - 1)][SIZE_OF_VALUE]));
    
    if (!name[0]) {
        strcpy(name, backup);
    }
    
    //LOGSTR1("Name is [%s]\n",(u32)name);


	sceIoClose(fid);
}

/*
 * Function to filter out "official" games
 * these games are usually in the form XXXX12345
*/
int not_homebrew(const char * name)
{
    int i;
    
    if (strlen(name) == 0) return 1;
    //official games are in the form: XXXX12345
    if (strlen(name) != 9) return 0;
    for (i = 4; i < 9; ++i)
    {
        if (name[i] < '0' || name[i] > '9')
            return 0;
    }
    
    return 1;
}

void helpAndCredits()
{
	cls();
	
	SetupCallbacks();

	
	// setup GU

	void* fbp0 = getStaticVramBuffer(BUF_WIDTH,SCR_HEIGHT,GU_PSM_8888);
	void* fbp1 = getStaticVramBuffer(BUF_WIDTH,SCR_HEIGHT,GU_PSM_8888);
	void* zbp = getStaticVramBuffer(BUF_WIDTH,SCR_HEIGHT,GU_PSM_4444);

	sceGuInit();

	sceGuStart(GU_DIRECT,list);
	sceGuDrawBuffer(GU_PSM_8888,fbp0,BUF_WIDTH);
	sceGuDispBuffer(SCR_WIDTH,SCR_HEIGHT,fbp1,BUF_WIDTH);
	sceGuDepthBuffer(zbp,BUF_WIDTH);
	sceGuOffset(2048 - (SCR_WIDTH/2),2048 - (SCR_HEIGHT/2));
	sceGuViewport(2048,2048,SCR_WIDTH,SCR_HEIGHT);
	sceGuDepthRange(65535,0);
	sceGuScissor(0,0,SCR_WIDTH,SCR_HEIGHT);
	sceGuEnable(GU_SCISSOR_TEST);
	sceGuDepthFunc(GU_GEQUAL);
	sceGuEnable(GU_DEPTH_TEST);
	sceGuFrontFace(GU_CW);
	sceGuShadeModel(GU_SMOOTH);
	sceGuEnable(GU_CULL_FACE);
	sceGuEnable(GU_TEXTURE_2D);
	sceGuEnable(GU_CLIP_PLANES);
	sceGuFinish();
	sceGuSync(0,0);

	sceDisplayWaitVblankStart();
	sceGuDisplay(GU_TRUE);

	

	// run sample

	int val = 0;

	while(running())
	{
		sceGuStart(GU_DIRECT,list);

		// clear screen

		sceGuClearColor(0xff554433);
		sceGuClearDepth(0);
		sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT);

		// setup matrices for cube

		sceGumMatrixMode(GU_PROJECTION);
		sceGumLoadIdentity();
		sceGumPerspective(75.0f,16.0f/9.0f,0.5f,1000.0f);

		sceGumMatrixMode(GU_VIEW);
		sceGumLoadIdentity();

		sceGumMatrixMode(GU_MODEL);
		sceGumLoadIdentity();
		{
			ScePspFVector3 pos = { 0, 0, -2.5f };
			ScePspFVector3 rot = { val * 0.79f * (GU_PI/180.0f), val * 0.98f * (GU_PI/180.0f), val * 1.32f * (GU_PI/180.0f) };
			sceGumTranslate(&pos);
			sceGumRotateXYZ(&rot);
		}

		// setup texture

		sceGuTexMode(GU_PSM_4444,0,0,0);
		sceGuTexFunc(GU_TFX_ADD,GU_TCC_RGB);
		sceGuTexEnvColor(0xffff00);
		sceGuTexFilter(GU_LINEAR,GU_LINEAR);
		sceGuTexScale(1.0f,1.0f);
		sceGuTexOffset(0.0f,0.0f);
		sceGuAmbientColor(0xffffffff);
		
	
		// draw cube

		sceGumDrawArray(GU_TRIANGLES,GU_TEXTURE_32BITF|GU_COLOR_8888|GU_VERTEX_32BITF|GU_TRANSFORM_3D,12*3,0,vertices);

		sceGuFinish();
		sceGuSync(0,0);

	

	printTextScreen(0, 0, "Credits/Controls", textColour);
	printTextScreen(0, 30, "Up and Down to scroll.", textColour);
	printTextScreen(0, 41, "Cross or Circle to launch homebrew.", textColour);
	printTextScreen(0, 52, "L to list homebrew by folder names.", textColour);
	printTextScreen(0, 63, "R to list homebrew by EBOOT names.", textColour);
	printTextScreen(0, 74, "Triangle to exit HBL menu.", textColour);
	printTextScreen(0, 85, "Select to return to the HBL menu.", textColour);
	printTextScreen(0, 94, "Analog + Left/Right to change colour quantities ", textColour);
	printTextScreen(0, 103, "Analog + Up/Down to change colour categories ", textColour);


	printTextScreen(0, 208, "MenuZero v0.01 by NightStar3", textColour);
	printTextScreen(0, 218, "A big thanks goes out to Mr. X for helping with MenuZero", textColour);
	printTextScreen(0, 227, "Half Byte Loader BETA by m0skit0, ab5000, wololo, davee", textColour);
	printTextScreen(0, 238, "Thanks to n00b81, Tyranid, devs of the PSPSDK, Hitmen,", textColour);
	printTextScreen(0, 249, "Fanjita & Noobz, psp-hacks.com", textColour);
	printTextScreen(0, 260, "GPL License: give the sources if you distribute binaries!!!", textColour);

	sceDisplayWaitVblankStart();
	sceGuSwapBuffers();

		val++;
	}

	sceGuTerm();

	
 } 
void refreshMenu(int offSet, char* menuData, int loadedCache)
{
  	int i;
	u32 color;
	cls();
	if (refreshType == 0) 
	{
		for(i = offSet; i < (MAXMENUSIZE + offSet); ++i)
		{
			color = textColour;
			if (i == currentFile)
				color = selectedColour;
			printTextScreen(0, 15 + (i - offSet) * 12, folders[i], color);
		}
	}
	else if (refreshType == 1) 
	{
		for(i = offSet; i < (MAXMENUSIZE + offSet); ++i) 
		{
			color = textColour;
			if (i == currentFile)
				color = selectedColour;
			if (loadedCache == 1) 
			{
				printTextScreen(0, 15 + (i - offSet) * 12, folders[i], color);
			} else {
				printTextScreen(0, 15 + (i - offSet) * 12, &menuData[MAX_NAME_SIZE*i], color);
			}
		}
	}
}

void setEboot() 
{
  	strcat(ebootPath, folders[currentFile]);
  	strcat(ebootPath, "/EBOOT.PBP");
  	//LOGSTR0(ebootPath);
  	isSet = 1;
}
/*
 * hexascii to integer conversion
 */
static int xstrtoi(char *str, int len) {
	int val;
	int c;
	int i;

	val = 0;
    for (i = 0; i < len; i++){
        c = *(str + i);
        fprintf(stderr, "character: %c", c);
		if (c >= '0' && c <= '9') {
			c -= '0';
		} else if (c >= 'A' && c <= 'F') {
			c = (c - 'A') + 10;
		} else if (c >= 'a' && c <= 'f') {
			c = (c - 'a') + 10;
		} else {
			return 0;
		}
		val *= 16;
		val += c;
	}
	return (val);
}

int init(char* menuData)
{

 	int i;
	SceUID id;
	SceIoDirent entry;
	nbFiles = 0;
	for (i = 0; i < NB_FOLDERS; ++i)
		folders[i][0] = 0;
  	id = sceIoDopen(ebootPath);

  	if (id < 0) 
	{
    	//LOGSTR1("FATAL: Menu can't open directory %s \n", (u32)ebootPath);
        printTextScreen(0, 205 , "Unable to open GAME folder (syscall issue?)", textColour);
    	loadCache();
    	return 1;
  	}	
  
 	memset(&entry, 0, sizeof(SceIoDirent));
	
  	while (sceIoDread(id, &entry) > 0 && nbFiles < NB_FOLDERS)
  	{
    	if (strcmp(".", entry.d_name) == 0 || strcmp("..", entry.d_name) == 0 || not_homebrew(entry.d_name)) 
		{
        	memset(&entry, 0, sizeof(SceIoDirent)); 
        	continue;
    	}
         
    	strcpy(folders[nbFiles], entry.d_name);
    	nbFiles++;
    	memset(&entry, 0, sizeof(SceIoDirent)); 
  	}
	
  	sceIoDclose(id);
	
	char fileBuffer[FILE_BUFFER_SIZE];
	char EbootName[MAX_NAME_SIZE];

	// clear the array, seems to be alot of trash left in memory
	for(i = 0; i < NB_FOLDERS; i++ ) 
	{
		memset(&menuData[i * MAX_NAME_SIZE],'\0',MAX_NAME_SIZE);
	}

	for(i = 0; i < nbFiles; i++) 
	{
		memset(fileBuffer,'\0',FILE_BUFFER_SIZE);
		memset(EbootName,'\0',MAX_NAME_SIZE);

		// builds path to eboot	
		strcat(fileBuffer, ebootPath);
		strcat(fileBuffer, folders[i]);
		strcat(fileBuffer, "/EBOOT.PBP");

		readEbootName(fileBuffer, folders[i], EbootName);
		strcpy(&menuData[MAX_NAME_SIZE*i],EbootName);

	}

  	if (!nbFiles) 
	{
        printTextScreen(0, 205 , "No files found in GAME folder (syscall issue?)", textColour);
    	loadCache();
  	}
	
	saveCache();
	return 0;
}

int main(int argc, char *argv[])
{
	
	
	      SetupCallbacks();
          initGraphics(); 

		  
		   
	SceCtrlData pad; // variable to store the current state of the pad
	 
	
       
	int menuOffSet = 0;
	char menuEntry[NB_FOLDERS][MAX_NAME_SIZE];
	int i;
	char buffer[20];
    char dummy_filename[256];
    strcpy(dummy_filename, "ms0:/PSP/GAME");
    currentFile = 0;
	
    int settingsAddr = 0;

    if (argc > 1) {
        char * hex = argv[1];
        *(hex + 8 ) = 0; //bug in HBL ?
        fprintf(stderr, "Location: 0x %s\n", hex);
        settingsAddr = xstrtoi(hex, 8);
    }
    fprintf(stderr, " settingsAddr : %d\n", settingsAddr);
    if (settingsAddr) {
        tMenuApi * settings = (tMenuApi *) settingsAddr;
        ebootPath = (void *) settings->filename;
    } else {
        ebootPath = dummy_filename;
    }
 
    //LOGSTR0("Start menu\n");
    isSet = 0;

    //LOGSTR0("MENU Sets display\n");
    
    //init screen
    sceDisplaySetFrameBuf(frameBuffer, 512, PSP_DISPLAY_PIXEL_FORMAT_8888, 1);
    //SetColor(backgroundColour);
	int loadSucess = init(&menuEntry[0][0]);

    //load folder's contents
	// if it loads the cache we want it to display folders[*], menuEntry would be empty
    //int loadSucess = init(&menuEntry[0][0]);
    
    refreshMenu(menuOffSet, &menuEntry[0][0], loadSucess);
	 
	int selComponent = 0;
    char filler[10]; 
		    
	 int bgR = 0;
     int bgG = 0;
     int bgB = 0; 

    Color highlightColor = RGB(200, 200, 200);
	Color dimmedColor = RGB(100, 100, 100);
    Color shadowColorH = RGB(55, 55, 55 );
    Color shadowColorD = RGB(55, 55, 55 ); 
	    
    sceKernelDelayThread(100000);
    do
	{
        sceCtrlReadBufferPositive (&pad, 1); // check the input.
		 if(pad.Ly == 0) {
                              if(selComponent > 0) {
                                        selComponent--;
                              }
                              for(i=0; i<10; i++) {
                                        sceDisplayWaitVblankStart();
                              }
                    } else if(pad.Ly == 255) {
                              if(selComponent < 2) {
                                        selComponent++;
                              }
                              for(i=0; i<10; i++) {
                                        sceDisplayWaitVblankStart();
                              }
                    } 
		 else if(pad.Lx == 255) {
                              switch(selComponent) {
                                        case 0:
                                                  bgR++;
                                                  break;
                                        case 1:
                                                  bgG++;
                                                  break;
                                        case 2:
                                                  bgB++;
                                                  break;
                                        default:
                                                  //SHOULD NEVER EXECUTE
                                                  break;
                              }
                    } else if(pad.Lx == 0) {
                              switch(selComponent) {
                                        case 0:
                                                  bgR--;
                                                  break;
                                        case 1:
                                                  bgG--;
                                                  break;
                                        case 2:
                                                  bgB--;
                                                  break;
                                        default:
                                                  //SHOULD NEVER EXECUTE
                                                  break;
                              }
                    }  if(bgR < 0) {
                              bgR = 0;
                    } else if(bgR > 255) {
                              bgR = 255;
                    }
                    if(bgG < 0) {
                              bgG = 0;
                    } else if(bgG > 255) {
                              bgG = 255;
                    }
                    if(bgB < 0) {
                              bgB = 0;
                    } else if(bgB > 255) {
                              bgB = 255;
                    } 

	else if(pad.Buttons & PSP_CTRL_SELECT) 
		{
			if (showInfo == 0) {
				showInfo = 1;
				helpAndCredits();
			}
			else if (showInfo == 1) {
				showInfo = 0;
				refreshMenu(menuOffSet, &menuEntry[0][0], loadSucess);
			}
			for(i=0; i<15; i++) 
			{
				sceDisplayWaitVblankStart();
			}
        }
		if (showInfo == 0) {
			if ((pad.Buttons & PSP_CTRL_CROSS) ||  (pad.Buttons & PSP_CTRL_CIRCLE))
			{ // if the cross or circle button is pressed
				//LOGSTR0("Menu sets EBOOT path: ");
				setEboot();			
			}
			else if ((pad.Buttons & PSP_CTRL_DOWN) && (currentFile < nbFiles - 1))
			{
				currentFile++;
				if(currentFile >= (MAXMENUSIZE + menuOffSet) && (nbFiles - 1) >= (MAXMENUSIZE + menuOffSet))
					menuOffSet++;
				refreshMenu(menuOffSet, &menuEntry[0][0], loadSucess);
				for(i=0; i<10; i++) 
				{
					sceDisplayWaitVblankStart();
				}
			}
			else if ((pad.Buttons & PSP_CTRL_UP) && (currentFile > 0) )
			{
				currentFile--;
				if(currentFile ==  menuOffSet && menuOffSet != 0)
					menuOffSet--;
				refreshMenu(menuOffSet, &menuEntry[0][0], loadSucess);
				for(i=0; i<10; i++) 
				{
					sceDisplayWaitVblankStart();
				}
			}
			else if(pad.Buttons & PSP_CTRL_TRIANGLE) 
			{
				strcpy(ebootPath, "quit");
				sceKernelExitGame();
			}
			else if(pad.Buttons & PSP_CTRL_LTRIGGER) 
			{
				if (refreshType == 1)
				{
					refreshType = 0;
					refreshMenu(menuOffSet, &menuEntry[0][0], loadSucess);
				}	
			}		
			else if(pad.Buttons & PSP_CTRL_RTRIGGER) 
			{
				if (refreshType == 0)
				{
					refreshType = 1;
					refreshMenu(menuOffSet, &menuEntry[0][0], loadSucess);
				}
			}
			
			fillScreenRect(RGB(bgR, bgG, bgB), 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); 
			 
			sprintf(filler, " RED: %i", bgR);
                    if(selComponent == 0) {
                              printTextScreen(11, 10, filler, shadowColorH);
                              printTextScreen(10, 10, filler, highlightColor);
                    } else {
                              printTextScreen(11, 10, filler, shadowColorD);
                              printTextScreen(10, 10, filler, dimmedColor);
                    } 

					 sprintf(filler, "GREEN: %i", bgG);
                    if(selComponent == 1) {
                              printTextScreen(11, 20, filler, shadowColorH);
                              printTextScreen(10, 20, filler, highlightColor);
                    } else {
                              printTextScreen(11, 20, filler, shadowColorD);
                              printTextScreen(10, 20, filler, dimmedColor);
                    }

                    sprintf(filler, " BLUE: %i", bgB);
                    if(selComponent == 2) {
                              printTextScreen(11, 30, filler, shadowColorH);
                              printTextScreen(10, 30, filler, highlightColor);
                    } else {
                              printTextScreen(11, 30, filler, shadowColorD);
                              printTextScreen(10, 30, filler, dimmedColor);
                    } 
			itoa((currentFile + 1), buffer, 10);
			printTextScreen(5, 0, buffer, textColour);
			itoa(nbFiles, buffer, 10);
			printTextScreen(30, 0, buffer, textColour);
			printTextScreen(21, 0, "/", textColour);
			printTextScreen(200, 0, "Press select for controls/credits.", textColour);
		}
        sceKernelDelayThread(100000);
    } while (!isSet);
	
	flipScreen();

                    for(i=0; i<1; i++) {
                              sceDisplayWaitVblankStart();
                    
         
					}
    //This point is reached when the value is set
    sceKernelExitGame();
    return 0;
}